package com.fowo.api.sms.service.impl;

import com.fowo.api.sms.config.VerificationCodeProperties;
import com.fowo.api.sms.service.SmsService;
import com.fowo.api.sms.service.VerificationCodeService;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;

@Service
@EnableConfigurationProperties(VerificationCodeProperties.class)
public class VerificationCodeServiceImpl implements VerificationCodeService {
    public static final String REDIS_KEY_FORMAT = "VerificationCode.%s";
    private static final String CHARS_NUMBER = "0123456789";
    private static final String CHARS_LETTER_AND_NUMBER = "0123456789abcdefghijklmnopqrstuvwxyz";
    @Resource
    private VerificationCodeProperties verificationCodeProperties;
    @Resource
    private RedisTemplate<String, Object> redisTemplate;
    @Resource
    private SmsService smsService;

    private String createCode() {
        return RandomStringUtils.random(
                verificationCodeProperties.getLen(),
                verificationCodeProperties.getType() == VerificationCodeProperties.CodeType.LETTER_AND_NUMBER ? CHARS_LETTER_AND_NUMBER : CHARS_NUMBER
        );
    }

    @Override
    public void sendCode(String phone) throws Exception {
        if(verificationCodeProperties.getDebugPhoneNumbers() != null && verificationCodeProperties.getDebugPhoneNumbers().contains(phone)) {
            // 调试忽略此手机号
            return;
        }
        String code = createCode();
        smsService.sendVerificationCode(phone, code);
        redisTemplate.opsForValue().set(String.format(REDIS_KEY_FORMAT, phone), code, verificationCodeProperties.getValidDuration());
    }

    @Override
    public boolean verification(String phone, String code) {
        if(verificationCodeProperties.getDebugPhoneNumbers() != null && verificationCodeProperties.getDebugPhoneNumbers().contains(phone)) {
            // 调试忽略此手机号
            return true;
        }
        String redisKey = String.format(REDIS_KEY_FORMAT, phone);
        String sentCode = (String) redisTemplate.opsForValue().get(redisKey);
        if(StringUtils.hasText(sentCode)) {
            if(!sentCode.equalsIgnoreCase(code)) {
                return false;
            }
            if (!verificationCodeProperties.isCanRepeatValidation()) {
                redisTemplate.delete(redisKey);
            }
            return true;
        }
        return false;
    }
}
